#include "ringbuffer.h"
#include <stdio.h>
#include <string.h>

#define BUFFER_SIZE 256

void print_buffer_status(CircularBufferContext *context)
{
  printf("Buffer Status:\n");
  printf("  Capacity: %u\n", context->capacity);
  printf("  Write Position: %u\n", context->write_pos);
  printf("  Read Position: %u\n", context->read_pos);
  printf("  Used Space: %d\n", circular_buffer_used_space(context));
  printf("  Available Space: %d\n", circular_buffer_available_space(context));
}

int main()
{
  printf("Circular Buffer Test Program\n");

  // Create a circular buffer
  CircularBufferContext context;
  uint8_t buffer_data[BUFFER_SIZE];
  context.data = buffer_data;
  context.capacity = BUFFER_SIZE;
  context.write_pos = 0;
  context.read_pos = 0;

  print_buffer_status(&context);

  // Test data
  const char *test_string = "This is a test string for circular buffer operations.";
  uint32_t str_len = strlen(test_string) + 1; // Include null terminator

  printf("\nWriting to buffer...\n");
  uint32_t written = write_to_circular_buffer((void *)test_string, 1, str_len, &context);
  printf("Written %u bytes\n", written);

  print_buffer_status(&context);

  // Read the data back
  printf("\nReading from buffer...\n");
  char read_buffer[BUFFER_SIZE];
  uint32_t read = read_from_circular_buffer(read_buffer, 1, str_len, &context);
  printf("Read %u bytes: %s\n", read, read_buffer);
  print_buffer_status(&context);

  // Test wrap-around
  printf("\nTesting wrap-around...\n");
  const char *long_string = "This is a much longer string that should cause the buffer to wrap around because it exceeds the initial buffer capacity we've defined for this test case.";
  uint32_t long_str_len = strlen(long_string) + 1;

  printf("Writing long string (%u bytes)...\n", long_str_len);
  written = write_to_circular_buffer((void *)long_string, 1, long_str_len, &context);
  printf("Written %u bytes\n", written);
  print_buffer_status(&context);

  printf("Reading long string...\n");
  read = read_from_circular_buffer(read_buffer, 1, long_str_len, &context);
  printf("Read %u bytes: %s\n", read, read_buffer);
  print_buffer_status(&context);


  // Test memory buffer
  printf("\nTesting MemoryHandle...\n");
  MemoryHandle *mem = init_circular_buffer(128);
  if (!mem) {
    printf("Failed to create memory buffer\n");
    return 1;
  }

  printf("circular_buffer_available_space %d\n", circular_buffer_available_space(mem));
  printf("circular_buffer_used_space %d\n", circular_buffer_used_space(mem));

  printf("Writing to memory buffer...\n");
  written = write_to_circular_buffer((void *)test_string, 1, str_len, mem);
  printf("Written %u bytes\n", written);

  printf("circular_buffer_available_space %d\n", circular_buffer_available_space(mem));
  printf("circular_buffer_used_space %d\n", circular_buffer_used_space(mem));

  printf("Reading from memory buffer...\n");
  read = read_from_circular_buffer(read_buffer, 1, str_len, mem);
  printf("Read %u bytes: %s\n", read, read_buffer);

  uninit_circular_buffer(mem);

  printf("\nAll tests completed.\n");
  return 0;
}